﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Galoap
{
    partial class Question
    {

        /// <summary>
        /// Given a questionID returns the question data
        /// </summary>
        /// <param name="questionID"></param>
        /// <returns></returns>
        public static Question GetQuestionByID(int questionID)
        {
            return GaloapDatabase.Database.Question.First(q => q.QuestionID == questionID);
        }

        public static List<Question> GetQuestionsFromGameSession(GameSession s)
        {
            s.GameReference.Load();
            s.Game.Question.Load();
            return s.Game.Question.Where(q => q.Level == s.Level).ToList();
        }

        public static Question GetRandomQuestionFromGameSession(GameSession s)
        {
            List<Question> list = GetQuestionsFromGameSession(s);
            Random r = new Random();
            return list.ElementAt(r.Next(list.Count));
        }

        public List<T> GetDistinctAnswersOrderedByFrequency<T>() where T : Answer
        {
            this.Answer.Load();
            return (from answer in this.Answer.OfType<T>()
                    orderby answer.Counter descending
                    select answer).Distinct().ToList();
        }

        public List<T> GetAnswersOrderedByFrequency<T>() where T : Answer
        {
            if (Answer.Count <= 0)
                this.Answer.Load();
            return (from answer in this.Answer.OfType<T>()
                    orderby answer.Counter descending
                    select answer).ToList();
        }
        
        public List<T> GetMostFrequentAnswer<T>() where T : Answer
        {
            this.Answer.Load();
            return (from answer in this.Answer.OfType<T>()
                     group answer by answer.Counter into ansGroup
                     orderby ansGroup.Count() descending
                     select ansGroup).First().ToList();
            //return GetAnswersOrderedByFrequency<T>().First();
        }

        public int GetMostFrequentAnswerCount<T>() where T : Answer
        {
            return GetMostFrequentAnswer<T>().First().Counter;
        }


        public List<T> GetAnswersWithCountGreaterThan<T>(int n) where T : Answer
        {
            this.Answer.Load();
            return (from answer in this.Answer.OfType<T>()
                    where answer.Counter > n
                    orderby answer.Counter ascending
                    select answer).ToList();
        }

        public List<T> GetAnswersWithCountSmallerThan<T>(Question qi, int n) where T : Answer
        {
            qi.Answer.Load();
            return (from answer in qi.Answer.OfType<T>()
                    where answer.Counter < n
                    orderby answer.Counter ascending
                    select answer).ToList();
        }

        public List<T> GetAnswersWithCountSmallerThan<T>(int n) where T : Answer
        {
            return GetAnswersWithCountSmallerThan<T>(this, n);
        }

        public List<T> GetAnswersWithCountEqualTo<T>( int n) where T : Answer
        {
            this.Answer.Load();
            return (from answer in this.Answer.OfType<T>()
                    where answer.Counter == n
                    orderby answer.Counter ascending
                    select answer).ToList();
        }


        public double GetAnwserFrequencyDistance<T>(Answer answer) where T : Answer
        {
            List<T> answers = GetDistinctAnswersOrderedByFrequency<T>();
            double jumpfactor = 100 / answers.Count;
            double i = 0;
            foreach (Answer a in answers )
            {
                if (a.CompareData(answer)) return i;
                i+= jumpfactor;
            }
            return i;
        }

        public void Add(Answer answer)
        {
            this.Answer.Load();
            this.Answer.Add(answer);
        }

        /// <summary>
        /// Adds this to the database
        /// </summary>
        public void AddQuestionToDB()
        {
            GaloapDatabase.Database.AddToQuestion(this);
            GaloapDatabase.Database.SaveChanges();
        }

        /// <summary>
        /// Saves the current state of this in the database
        /// </summary>
        public void Save()
        {
            GaloapDatabase.Database.SaveChanges();
        }
    }
}
